package com.ruoyi.ai.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
import com.ruoyi.ai.api.bo.WxPhoneLoginBo;
import com.ruoyi.ai.api.vo.ExpInfo;
import com.ruoyi.ai.api.vo.WxLoginVo;
import com.ruoyi.ai.config.WxMaProperties;
import com.ruoyi.ai.domain.WxUser;
import com.ruoyi.ai.domain.bo.WxUserBo;
import com.ruoyi.ai.service.IWxNumChangeService;
import com.ruoyi.ai.service.IWxUserService;
import com.ruoyi.ai.service.WxBizService;
import com.ruoyi.common.enums.DeviceType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.system.service.SysLoginService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;

import static com.ruoyi.common.constant.UserConstants.WX_USER_NORMAL;
import static com.ruoyi.common.constant.UserConstants.WX_USER_NOT_NORMAL;

@Service
@Slf4j
public class WxBizServiceImpl implements WxBizService {
    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private IWxUserService wxUserService;
    @Autowired
    private SysLoginService sysLoginService;

    @Autowired
    private WxMaProperties properties;
    @Autowired
    private IWxNumChangeService wxNumChangeService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public WxLoginVo login(String code) {
        if (StringUtils.isBlank(code)) {
            throw new IllegalArgumentException("code不能为空");
        }
        //由于只配置一个，直接获取配置即可
        try {
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
            String openid = session.getOpenid();
            String unionid = session.getUnionid();
            log.info("openid:{}", openid);
            log.info("unionid:{}", unionid);
            WxLoginVo loginVo = new WxLoginVo();
            loginVo.setOpenid(openid);
            loginVo.setLoginToken(getToken(openid, unionid));
            if (loginVo.getLoginToken() != null) {
                loginVo.setExpInfo(this.buildExpInfo());
            }
            return loginVo;
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            throw new ServiceException("登录异常" + e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public WxLoginVo loginByPhone(WxPhoneLoginBo request) {
//        WxUser wxUser = wxUserService.queryByOpenid(request.getOpenid());
//        if (wxUser == null) {
//            throw new ServiceException("当前用户不存在");
//        }
//        // 新版获取手机号
//        try {
//            WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(request.getCode());
//            log.info("获取手机号信息,{}", JsonUtils.toJsonString(phoneNoInfo));
//            String phoneNumber = phoneNoInfo.getPhoneNumber();
//            WxUserBo update = new WxUserBo();
//            update.setPhone(phoneNumber);
//            update.setWxUserId(wxUser.getWxUserId());
//            update.setRegisterTime(new Date());
//            update.setStatus(WX_USER_NORMAL);
//            //注册赠送次数
//            wxNumChangeService.registerGiveNum(update);
//            wxUserService.updateByBo(update);
//            String token = sysLoginService.wxUserLogin(wxUser.getWxUserId(), request.getOpenid(), DeviceType.XCX_CUSTOMER);
//            ExpInfo expInfo = token == null ? null : this.buildExpInfo();
//            return new WxLoginVo(token, request.getOpenid(), expInfo);
//        } catch (WxErrorException e) {
//            log.error("微信获取手机号异常:", e);
//            throw new ServiceException("微信异常");
//        } finally {
//            WxMaConfigHolder.remove();//清理ThreadLocal
//        }
        throw new ServiceException("暂不支持");
    }

    /**
     * 模拟登录，方便后端调试接口
     *
     * @param request
     * @return
     */
    @Override
    public WxLoginVo mockLogin(WxPhoneLoginBo request) {
        WxUser wxUser = wxUserService.queryByOpenid(request.getOpenid());
        if (wxUser == null) {
            throw new ServiceException("用户不存在");
        }
        String token = sysLoginService.wxUserLogin(wxUser.getWxUserId(), wxUser.getOpenid(),DeviceType.XCX_CUSTOMER);
        return new WxLoginVo(token, wxUser.getOpenid(), this.buildExpInfo());
    }

    public String getToken(String openid, String unionId) {
        if (!RedisUtils.setObjectIfAbsent(this.buildRedisKey(openid), "", Duration.ofMillis(2000))) {
            throw new ServiceException("重复登录");
        }
        try {
            WxUser wxUser = wxUserService.queryByOpenid(openid);
            Long wxUserId = null;
            if (wxUser == null) {
                WxUserBo addUser = new WxUserBo();
                addUser.setAppId(wxMaService.getWxMaConfig().getAppid());
                addUser.setOpenid(openid);
                //自动注册
                addUser.setStatus(WX_USER_NORMAL);
                addUser.setUnionid(unionId);
                addUser.setRegisterTime(new Date());
                wxUserService.insertByBo(addUser);
                //注册赠送次数
                wxNumChangeService.registerGiveNum(addUser);
                wxUserId = addUser.getWxUserId();
            }else{
                wxUserId = wxUser.getWxUserId();
            }
            return sysLoginService.wxUserLogin(wxUserId, openid,DeviceType.XCX_CUSTOMER);
        } finally {
            RedisUtils.deleteObject(this.buildRedisKey(openid));
        }

    }

    private String buildRedisKey(String openid) {
        return "login_" + openid;
    }

    private ExpInfo buildExpInfo() {
        ExpInfo expInfo = new ExpInfo();
        //此处根据自己的需求增加，例如订阅消息的模板id
        expInfo.setSomeIds(new ArrayList<>());
        return expInfo;
    }
}
